﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Net.Sockets;
using MUD.Network;
using MUD.Driver.Log;
using MUD.Data;
using MUD.Lib;
using MUD.Lib.Utils;
using System.Threading;

namespace MUD.Driver
{
    public partial class CommandConsole : Form
    {
        delegate void LogCallback(string line);
        delegate void CloseCallback();

        SocketServer Server;
        Master MasterObject;

        public CommandConsole()
        {
            InitializeComponent();
            Shown += new EventHandler(CommandConsole_Shown);
            FormClosing += new FormClosingEventHandler(CommandConsole_FormClosing);
            DriverLog.LogfilePath = @"Driver.html";
            DriverLog.Initialize();
        }

        void CommandConsole_FormClosing(object sender, FormClosingEventArgs e)
        {

        }

        void CommandConsole_Shown(object sender, EventArgs e)
        {
            // Start the socket server.
            Server = new SocketServer();
            Server.OnLog += new EventHandler<MUD.Network.LogEventArgs>(SocketServer_OnLog);
            Server.OnReceive += new EventHandler<ReceiveEventArgs>(SocketServer_OnRecieve);
            Server.OnConnectionStateChange += new EventHandler<ConnectionEventArgs>(SocketServer_OnConnectionStateChange);
            Server.Initialize(Driver.Default.MaxUsers, Driver.Default.MaxIncomingBufferSize, Driver.Default.ListenerHost, Driver.Default.ListenerPort);
            Server.Start();

            // Instantiate the database provider.
            Provider.ConnectionString = Data.Default.DBConnectionString;
            Provider.OnLog += new EventHandler<MUD.Data.LogEventArgs>(provider_OnLog);

            // Hook all of this into the MUD Master Object
            MasterObject = new Master(Server);
            MasterObject.OnLog += new EventHandler<MUD.Network.LogEventArgs>(MasterObject_OnLog);
            MasterObject.OnShutdown += new EventHandler<ShutdownEventArgs>(Master_OnShutdown);
            MasterObject.HeartbeatInterval = Driver.Default.HeartbeatInterval;
            MasterObject.Initialize();
        }

        void Master_OnShutdown(object sender, ShutdownEventArgs e)
        {
            Broadcast("Server going down by request of " + e.Username + ": " + e.Reason);
            Thread.Sleep(1000);
            if (!this.InvokeRequired)
            {
                Close();
            }
            else
            {
                CloseCallback temp = new CloseCallback(this.Close);
                Invoke(temp);
            }
        }

        void MasterObject_OnLog(object sender, MUD.Network.LogEventArgs e)
        {
            WriteLine(e.Message);
            DriverLog.WriteLine(e.Message);
        }

        void provider_OnLog(object sender, MUD.Data.LogEventArgs e)
        {
            WriteLine(e.Message);
            DriverLog.WriteLine(e.Message);
        }

        void SocketServer_OnConnectionStateChange(object sender, ConnectionEventArgs e)
        {
            switch (e.Event)
            {
                case ConnectionEventType.Connected:
                    e.Client.Write(ANSI.ColorCode(ANSI.Codes.Bold) + ANSI.ColorCode(ANSI.Codes.Red) + "Welcome to my test server!" + ANSI.ColorCode(ANSI.Codes.Reset) + Environment.NewLine);
                    break;
                case ConnectionEventType.Disconnected:
                    break;
            }
                
        }

        void SocketServer_OnRecieve(object sender, ReceiveEventArgs e)
        {
            SocketServer_OnLog(sender, new MUD.Network.LogEventArgs("Recieved message from " + e.Client.ToString() + ": " + e.Message));
        }

        void SocketServer_OnLog(object sender, MUD.Network.LogEventArgs e)
        {
            WriteLine(e.Message);
            DriverLog.WriteLine(e.Message);
        }

        /// <summary>
        /// Wait for an "enter" keypress in the textbox, and call the submit button's "click" method
        /// </summary>
        /// <param name="keyData">Key pressed</param>
        /// <returns>Did we consume this keypress event?</returns>
        protected override bool ProcessDialogKey(Keys keyData)
        {
            if (keyData == Keys.Enter && txtEntry.Focused)
            {
                btnSend_Click(this, new EventArgs());
                return true;
            }
            return base.ProcessDialogKey(keyData);
        }


        public void WriteLine(string line)
        {
            if (!rtbConsole.InvokeRequired)
            {
                rtbConsole.Text += line + Environment.NewLine;
                Win32.ScrollRichTextBox(rtbConsole);
            }
            else
            {
                LogCallback temp = new LogCallback(WriteLine);
                this.Invoke(temp, new object[] { line });
            }
        }

        public void Write(string line)
        {
            if (!rtbConsole.InvokeRequired)
            {
                rtbConsole.Text += line;
                Win32.ScrollRichTextBox(rtbConsole);
            }
            else
            {
                LogCallback temp = new LogCallback(WriteLine);
                this.Invoke(temp, new object[] { line });
            }

        }

        private void btnSend_Click(object sender, EventArgs e)
        {

        }

        private void optionsToolStripMenuItem_Click(object sender, EventArgs e)
        {
            ActiveConnections ac = new ActiveConnections();
            ac.PopulateListBox(Server);
            ac.Show();
        }

        public void Broadcast(string message)
        {
            foreach (AsyncClient client in Server.Clients)
            {
                client.Write(message);
            }
        }

    }
}
